home *** CD-ROM | disk | FTP | other *** search
- #import "CreepyFaceView.h"
- #import <math.h>
- #import "CFWireFrame.h"
- #import <sys/dir.h>
- #import <sys/types.h>
- #import <objc/NXBundle.h>
-
- @class CFWireFrame;
-
- // this code is copyright Darcy Brockbank, 1993
- //
- // You may freely reuse and distribute this code in any way shape or
- // form, provided that this notice stays intact.
- //
- // darcy@hasc.ca, samurai@cs.mcgill.ca
- //
- // StefView was implemented out of WorldSpaceView and retains some of the
- // movement properties...
- //
- // The code for WorldSpaceView was written by Sam Streeper at CreepyFace, I think,
- // and there were two other contributors, but I can't find their names in the
- // source for it.
- //
- // CreepyFaceView shows a simple (ha!) spinning CreepyFace, in full 3D. The 3D code
- // came from an app I wrote a long time ago called "CFWireFrame", and so the code
- // is pretty scary. As well, this thing is only a quick hack, though a nice one.
- //
- // This thing has room for improvement, and if you do so, send me a copy!
- //
- // - darcy
-
- @implementation CreepyFaceView
-
-
- #define X_PERIOD 15000.0
- #define Y_PERIOD 12000.0
- #define DEFAULT_FPS 10
- #define PI 3.1415926535
- #define SIZE 256.0
- #define MAX_IMAGE_WIDTH SIZE
- #define MAX_IMAGE_HEIGHT SIZE
- #define MAX_X_SPEED (26)
- #define MAX_Y_SPEED (26)
- #define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
- #define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
- #define PRINT(a) printf(a)
-
- #define MINX 0.0
- #define MINY 0.0
-
-
- #define ZOOM 680.0
-
- - takeSpot:(float)x:(float)y;
- {
- [self draw];
- return self;
- }
-
- - takeSnapshot;
- {
- return self;
- }
-
- - oneStep
- {
- NXRect black = {0,0,0,0};
- NXRect ballRect;
- BRECT new;
- static float xdelt = 2.0;
- static float ydelt = 2.0;
- int changed = 0;
-
- then = now;
- now = currentTimeInMs();
-
- xpos += xdelt;
- if (xpos<MINX) {
- xpos = MINX;
- xdelt*=-1.0;
- changed=1;
- } else if (xpos>maxCoord.x){
- xpos = maxCoord.x;
- xdelt*=-1.0;
- changed=1;
- }
- ypos += ydelt;
- if (ypos<MINY) {
- ypos = MINY;
- ydelt*=-1.0;
- changed=1;
- } else if (ypos>maxCoord.y){
- ypos = maxCoord.y;
- ydelt*=-1.0;
- changed=1;
- }
-
- if (changed){
- #if 0
- Axis flip[3]={y,y,y};
- Direction dir[2]={positive,positive};
- #else
- Axis flip[3]={y,z,x};
- Direction dir[2]={positive,negative};
- #endif
-
- axis = flip[axis];
- spin = dir[spin];
- }
-
- new.l = floor(xpos);
- new.b = floor(ypos);
- new.r = new.l + imageSize.width;
- new.t = new.b + imageSize.height;
-
-
- ballRect.origin.x = 0;
- ballRect.origin.y = 0;
- ballRect.size.width = imageSize.width;
- ballRect.size.height = imageSize.height;
-
- redrawTo.x = MIN(new.l, old.l);
- redrawTo.y = MIN(new.b, old.b);
-
- redraw.origin.x = 0;
- redraw.origin.y = 0;
- redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
- redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
-
- black.size= redraw.size;
-
-
- [buffer lockFocus];
- PSsetgray(0);
- NXRectFill(&black);
-
- [self draw];
-
- ballTo.x = new.l - redrawTo.x;
- ballTo.y = new.b - redrawTo.y;
-
- [buffer unlockFocus];
- [buffer composite:NX_COPY toPoint:&redrawTo];
- old = new;
- return self;
- }
-
-
-
- - initFrame:(const NXRect *)frameRect
- {
- const char *animSpeed;
- NXRect black = {0, 0, SIZE, SIZE };
-
- imageSize = black.size;
- [super initFrame:frameRect];
- [self allocateGState]; // For faster lock/unlockFocus
- [self setClipping:NO]; // even faster...
-
- PSsetlinewidth(0.15);
- backgroundColour=NX_COLORBLACK;
- worldOrigin.x=0.0;
- worldOrigin.y=0.0;
- worldOrigin.z=0.0;
- translationRate = 3.0;
- currentZoom=ZOOM;
- list = [[List alloc] init];
- axis = y;
- spin = positive;
-
- buffer = [[NXImage alloc] initSize:&black.size];
-
- if ([buffer lockFocus])
- {
- PSsetgray(0);
- NXRectFill(&black);
- [buffer unlockFocus];
- }
- animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed");
- if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS;
- else framesPerSecond = atoi(animSpeed);
- nextRotationTime = 0;
- [self newViewSize];
- return self;
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- [super sizeTo:width :height];
- [self newViewSize];
- return self;
- }
-
- - newViewSize
- {
- //this is called every time View size changes
- NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
-
- then = now = currentTimeInMs();
-
- if (oldSize.width == bounds.size.width &&
- oldSize.height == bounds.size.height)
- return self;
- else
- {
- oldSize.width = bounds.size.width;
- oldSize.height = bounds.size.height;
- }
-
- maxCoord.x = bounds.size.width - imageSize.width - MINX;
- maxCoord.y = bounds.size.height - imageSize.height - MINY;
- if (maxCoord.x < 0) maxCoord.x = 0;
- if (maxCoord.y < 0) maxCoord.y = 0;
-
-
- old.l = old.r = maxCoord.x/2 + MINX;
- old.b = old.t = maxCoord.y/2 + MINY;
- ballTo.x = ballTo.y = 0;
-
- if ([buffer lockFocus])
- {
- PSsetgray(0);
- NXRectFill(&black);
- [buffer unlockFocus];
- }
-
- return self;
- }
-
- - (const char *)windowTitle
- {
- return "CreepyFaceView";
- }
-
-
-
- - inspector:sender
- {
- char buf[MAXPATHLEN];
- if (!sharedInspectorPanel){
- sprintf(buf,"%s/CreepyFaceView.nib",[sender moduleDirectory:"CreepyFace"]);
- [NXApp loadNibFile:buf owner:self withNames:NO];
- [self loadDir:[sender moduleDirectory:"CreepyFace"]];
- }
- return sharedInspectorPanel;
- }
-
- - tryToChangeCentre
- {
- id object=[self firstObject];
- if (object) {
- [object getCentre:&curOrigin.x:&curOrigin.y:&curOrigin.z];
- } else {
- curOrigin.x = curOrigin.y = curOrigin.z = 0.0;
- }
- return self;
- }
-
- - firstObject
- {
- return [list objectAt:0];
- }
-
- - free
- {
- [list free];
- return [super free];
- }
-
- - (const char *)world;
- {
- return "CreepyFace.world";
- }
-
- - loadDir:(const char *)dir
- {
- char world[MAXPATHLEN+1];
- sprintf(world,"%s/%s",dir,[self world]);
- [self loadWorld:world];
- [self tryToChangeCentre];
- [self display];
- return self;
- }
-
- - loadWorld:(const char *)world
- {
- DIR *dirp;
- id newFrame;
- struct direct *dp;
- char *tail;
- char temp[1024];
-
-
- dirp=opendir(world);
- if (!dirp) {
- NXRunAlertPanel("Directory Error", "Can't read directory: %s","OK",0,0,world);
- } else {
- for(dp=readdir(dirp);dp!=NULL;dp=readdir(dirp)){
- if ((tail=(rindex(dp->d_name,'.')))!=NULL){
- if (strcmp((tail+1),"wireframe")==0){
- sprintf(temp,"%s/%s",world,dp->d_name);
- newFrame = [[CFWireFrame alloc] init];
- [newFrame makeCFWireFrame:temp];
- [self addThisObject:newFrame];
- [newFrame translate:negative alongAxis:z atRate:1200];
- }
- if (strcmp((tail+1),"wireframeb")==0){
- sprintf(temp,"%s/%s",world,dp->d_name);
- newFrame = [[CFWireFrame alloc] init];
- [newFrame readBinaryCodeFrom:temp];
- [self addThisObject:newFrame];
- [newFrame translate:negative alongAxis:z atRate:1200];
- }
- }
- }
- }
- return self;
- }
-
- - setTranslationRate:sender;
- {
- translationRate=[sender floatValue];
- return self;
- }
-
-
- - (int)numberOfObjects
- {
- return [list count];
- }
-
- - addThisObject:anObject
- {
- [list addObject:anObject];
- return self;
- }
-
- - setZoom: sender
- {
- currentZoom=[sender floatValue];
- [self display];
- return self;
- }
-
-
- - draw;
- {
- int i,count = [list count] ;
-
- for (i=0;i<count;i++){
- id wireFrame = [list objectAt:i];
- [wireFrame rotate:spin aroundAxis:axis atOrigin:curOrigin];
- [wireFrame drawYourself:currentZoom
- centeredOn:imageSize.width/2.0 :imageSize.height/2.0];
- }
- return self;
- }
-
- - translate:(Direction)dir alongAxis:(Axis)a atRate:(float)rate
- {
- int i,count = [list count];
- for (i=0;i<count;i++){
- [[list objectAt:i] translate:dir
- alongAxis:a
- atRate:rate];
- }
- [self tryToChangeCentre];
- return self;
- }
-
-
- - rotate:(Direction)dir aroundAxis:(Axis)a atOrigin:(Origin)orig
- {
- int i,count = [list count];
-
- for (i=0;i<count;i++){
- [[list objectAt:i] rotate:dir
- aroundAxis:a
- atOrigin:orig];
- }
- return self;
- }
-
- - rotatey:sender;
- {
- [self rotate:negative aroundAxis:y atOrigin:curOrigin];
- return self;
- }
- - rotateY:sender;
- {
- [self rotate:positive aroundAxis:y atOrigin:curOrigin];
- return self;
- }
- - rotatez:sender;
- {
- [self rotate:negative aroundAxis:z atOrigin:curOrigin];
- return self;
- }
- - rotateZ:sender;
- {
- [self rotate:positive aroundAxis:z atOrigin:curOrigin];
- return self;
- }
- - rotatex:sender;
- {
- [self rotate:negative aroundAxis:x atOrigin:curOrigin];
- return self;
- }
- - rotateX:sender;
- {
- [self rotate:positive aroundAxis:x atOrigin:curOrigin];
- return self;
- }
-
- @end
-